home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / web / noweb / contrib / gregory / dots.nw (.txt) < prev    next >
LaTeX Document  |  1995-02-24  |  6KB  |  123 lines

  1. \section*{Resolving trailing dots\ldots}
  2. Gregory Tucker-Kellogg\\
  3. gtk@walsh.med.harvard.edu
  4. \subsection*{Introduction}
  5. Unlike \verb|WEB|, \verb|noweb| does not allow the use of trailing
  6. dots in chunk (section) names. \verb|Dots| corrects for this.  It is
  7. similar but not identical to \verb|disambiguate|, an \verb|Icon|
  8. program to accomplish the same task.  \verb|Dots| is written in
  9. \verb|perl|.
  10. Before it does much else, \verb|noweb| creates a markup description of
  11. a source file.  That markup description is passed along (in both
  12. \verb|noweave| and \verb|notangle|) to other programs in the pipeline
  13. (\verb|totex| for \verb|noweave| and \verb|nt| for \verb|notangle|). 
  14. \verb|Dots| intervenes after the markup stage as a filter.  The chunk
  15. name references are passed in the form described in Ramsey's paper,
  16. i.e.,
  17. \begin{quote}
  18. \leavevmode\rlap{\begin{tabular}{ll}
  19. \tt @defn {\rm\it name}&The code chunk named {\rm\it name} is being defined\\
  20. \tt @use {\rm\it name}&A reference to code chunk named {\rm\it name}\\
  21. \end{tabular}}
  22. \end{quote}
  23. If trailing dots are used in a chunk name, they will be passed along
  24. at the markup stage verbatim without any attempt at resolution.
  25. That's where \verb|dots| comes in.
  26. We require two passes over the noweb code as passed through
  27. \verb|markup|.  The first pass picks out all of the unambigious chunk
  28. names and stores them in associative arrays.  In between the passes,
  29. we expand the ambigious names and do some simple error checking.  The
  30. second pass does a simple replace on incomplete names and writes
  31. output to the next stage of the pipeline.
  32. The choices for handling the input stream seems to be between sucking
  33. the whole markup into memory at once (as \verb|disambiguate| does) or storing
  34. the markup as a temporary file between the passes.  The second is
  35. slower but will not break as the file gets bigger.  We'll choose the
  36. first for now.
  37. \subsection*{Program outline}
  38. <<*>>=
  39. #!/usr/local/bin/perl
  40. while (<>) {     # the first pass takes the input from STDIN
  41.     <<create lists of identifiers>>
  42. <<resolve ambiguities in identifier names>>
  43. <<printout while replacing those with trailing dots>>
  44. \subsection*{Representation}
  45. What's the best structure for the list of chunk names?  It could just be a
  46. normal array, except we would have to check if a given name is already
  47. defined before adding it too the list. We could make an associative
  48. array, except we really don't have a key to associate.  On the other
  49. hand, we could make a single associative array of names with
  50. associations ``complete''  and ``incomplete'' depending on the
  51. presence of dots.  This would require no checking on predefinitions,
  52. and a key sorted list brings up each full chunk name as the {\em next}
  53. member of the list for which [[$completion{$identifier}=$complete]].  
  54. <<create lists of identifiers>>=
  55. if (/^@(defn|use)\s(.*)$/) { # we've found a name of some sort
  56.   if (($truncated = $2) =~ s/\.\.\.$//) { # this one ends in dots.
  57.     $completion{$truncated} ="incomplete";
  58.     $truncations{$.-1} = $truncated;
  59.     $usage_type{$.-1} = $1;
  60.   else {$completion{$2} ="complete";}
  61.   push(lines,$_);
  62. \subsection*{Chunkname resolution}
  63. The associative array [[%completion]] contains all of the names. The
  64. associative array [[%truncation_table]] contains the line numbers of the
  65. names with trailing dots.  We can change the values of [[%completion]]
  66. from ``complete'' and ``incomplete'' to a number representing the
  67. index of the appropriate completion.  If there is more than one, we
  68. can print out a warning but still resolve on the closest name.
  69. <<resolve ambiguities in identifier names>>=
  70. @namelist = sort(keys(%completion));
  71. $j = $i = 0;
  72. while ($i < $#namelist) { #collect all the ambiguities in a row
  73.   while ($completion{$namelist[$j]} eq "incomplete") {
  74.      $ambiguity_found = 1;
  75.      $j = $i + 1; 
  76.   <<check for remaining ambiguity>>  
  77.   foreach $name (@namelist[$i..$j]) { 
  78.         $completion{$name} = $namelist[$j];
  79.   $j=$i=$j + 1; 
  80.   undef($ambiguity_found);
  81. After we've gotten the expansions of abbreviated chunk names, we still
  82. might run into a problem.  First, if no correct expansion was
  83. established, we might just missassign the abbreviation.  The expansion
  84. might still be ambiguous if more than one complete expansion can give
  85. the same abbreviation.  The first case is a fatal error.  The second
  86. can be resolved by seeing if a complete chunkname immediately
  87. following the first completion is a solution.  If so, we take the
  88. first completion anyway but print a warning for the user.
  89. <<check for remaining ambiguity>>=
  90. if (defined $ambiguity_found) {
  91.    $suggested = $namelist[$j]; 
  92.    $nextchance =  $namelist[$j+1];
  93.    foreach $name (@namelist[$i..$j-1]) { 
  94.      if (substr($suggested,0,length($name)) ne $name) {
  95.          die "FATAL ERROR: can't resolve @<<$name...>>\n"
  96.      }
  97.    if ($completion{$nextchance} eq "complete") {
  98.      foreach $name (@namelist[$i..$j-1]) { 
  99.        if (substr($nextchance,0,length($name)) eq $name) {
  100.           print STDERR "WARNING--Ambiguous chunkname:\n";
  101.           print STDERR "\t<<${name}...@>> could be either\n";
  102.           print STDERR "\t<<$suggested@>> or\n\t<<$nextchance@>>\n";
  103.           print STDERR "I will use <<$suggested@>>\n"
  104.        }
  105.      }
  106. \subsection*{Printout}
  107. Finally, the [[%truncations]] and [[%usage_type]] arrays are put to
  108. work.  We use the line numbers (as [[keys()]]) to pull up the
  109. truncations, and then associate truncations with completed names.
  110. Since we found everything on the first pass we don't have to scan
  111. each line for a [[@defn]] or [[@use]] statement.  Note: this part of
  112. the program, analogous to {\em pass2} in \verb|disambiguate|, is
  113. different from \verb|disambiguiate|, which went through a search on
  114. the second pass.  If we decided to store the markup in a temporary
  115. file after the first pass to save memory, we would change this section
  116. for blockwise printout.  We still would not be forced to scan each
  117. line.
  118. <<printout while replacing those with trailing dots>>=
  119. foreach $trunc_line (sort(keys(%truncations))) {
  120.   $lines[$trunc_line] = 
  121.     "\@$usage_type{$trunc_line} $completion{$truncations{$trunc_line}}\n";
  122. print @lines;
  123.